// 将图片文件压缩到目标大小（约1M），保持宽高比
export function compressImageToTargetSize(file, targetSize) {
  const TARGET_SIZE = 1024 * 1024 // 1MB目标
  const MIN_QUALITY = 0.4 // 最低质量阈值
  const MIN_DIMENSION = 800 // 最小尺寸限制
  const MAX_DIMENSION = 5000 // 最大尺寸限制

  if (file.size <= TARGET_SIZE) {
    return Promise.resolve(file)
  }

  return new Promise((resolve, reject) => {
    const objectUrl = URL.createObjectURL(file)
    const img = new Image()
    img.src = objectUrl

    img.onload = () => {
      URL.revokeObjectURL(objectUrl)
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      const originalWidth = img.width
      const originalHeight = img.height
      // 计算原始宽高比（关键：全程保持此比例）
      const aspectRatio = originalWidth / originalHeight

      // 1. 初步缩放：超大型图片先缩放到合理范围（保持比例）
      let scaledWidth = originalWidth
      let scaledHeight = originalHeight

      if (scaledWidth > MAX_DIMENSION) {
        scaledWidth = MAX_DIMENSION
        scaledHeight = scaledWidth / aspectRatio // 用原始比例反推高度
      }
      if (scaledHeight > MAX_DIMENSION) {
        scaledHeight = MAX_DIMENSION
        scaledWidth = scaledHeight * aspectRatio // 用原始比例反推宽度
      }

      // 2. 精确计算目标尺寸（核心：基于比例的像素控制）
      const isPng = file.type.includes('png')
      const pixelRatio = isPng ? 0.00002 : 0.000012
      const targetPixels = TARGET_SIZE * 1.1 * pixelRatio // 预留10%质量调整空间
      const currentPixels = scaledWidth * scaledHeight

      // 如需进一步缩小，基于比例计算新尺寸
      if (currentPixels > targetPixels) {
        const scaleRatio = Math.sqrt(targetPixels / currentPixels)
        scaledWidth *= scaleRatio
        scaledHeight = scaledWidth / aspectRatio // 严格保持比例
      }

      // 3. 确保不小于最小尺寸（仍保持比例）
      if (scaledWidth < MIN_DIMENSION) {
        scaledWidth = MIN_DIMENSION
        scaledHeight = scaledWidth / aspectRatio
      }
      if (scaledHeight < MIN_DIMENSION) {
        scaledHeight = MIN_DIMENSION
        scaledWidth = scaledHeight * aspectRatio
      }

      // 4. 取整处理（避免小数像素导致的比例偏差）
      scaledWidth = Math.round(scaledWidth)
      // 用取整后的宽度反推高度，确保最终比例严格一致
      scaledHeight = Math.round(scaledWidth / aspectRatio)

      // 5. 绘制图片（使用精确计算的尺寸）
      canvas.width = scaledWidth
      canvas.height = scaledHeight
      ctx.drawImage(img, 0, 0, scaledWidth, scaledHeight)

      // 6. 质量调整（确保最终大小达标）
      canvas.toBlob(
        (blob) => {
          if (!blob) {
            reject(new Error('压缩失败'))
            return
          }

          if (blob.size > TARGET_SIZE) {
            // 如需调整，按比例降低质量（不改变尺寸）
            const quality = Math.max(MIN_QUALITY, TARGET_SIZE / blob.size)
            canvas.toBlob(
              (finalBlob) => {
                const finalFile = new File([finalBlob], file.name, {
                  type: file.type || 'image/jpeg',
                  lastModified: Date.now()
                })
                resolve(finalFile)
              },
              file.type || 'image/jpeg',
              quality
            )
          } else {
            const compressedFile = new File([blob], file.name, {
              type: file.type || 'image/jpeg',
              lastModified: Date.now()
            })
            resolve(compressedFile)
          }
        },
        file.type || 'image/jpeg',
        0.9 // 初始高质量尝试
      )
    }

    img.onerror = () => {
      URL.revokeObjectURL(img.src)
      reject(new Error('图片加载失败'))
    }
  })
}
/**
 * 将图片文件压缩到目标大小（约1M），保持宽高比
 * @param {File} file - 原始图片文件（需为JPEG/PNG格式）
 * @param {number} targetSize - 目标大小（单位：字节，默认1M）
 * @returns {Promise<File>} - 压缩后的图片文件
 */
export function compressImageToTargetSize2(file, targetSize = 1024 * 1024) {
  console.log('targetSize', targetSize)
  return new Promise((resolve, reject) => {
    // 验证文件类型
    if (!file.type.startsWith('image/')) {
      reject(new Error('仅支持图片文件（JPEG/PNG）'))
      return
    }
    // 计算压缩比例
    let compressionRatio
    if (file.size <= 1048576) {
      // 文件已小于目标大小，无需压缩
      resolve(file)
      return
    } else {
      compressionRatio = 1048576 / file.size
    }
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = (event) => {
      const img = new Image()
      img.src = event.target.result
      img.onload = () => {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        // 保持宽高比计算尺寸（以长边不超过原图的1.5倍为上限，避免过度放大）
        const maxWidth = img.width
        const maxHeight = img.height
        let width = img.width * compressionRatio
        let height = img.height * compressionRatio

        // 如果原图尺寸过大，先按比例缩放（减少后续压缩压力）
        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height)
          width *= ratio
          height *= ratio
        }
        canvas.width = width
        canvas.height = height
        ctx.drawImage(img, 0, 0, width, height)
        // 动态调整质量，直到文件大小接近目标值
        const tryCompress = (low = 0.1, high = 0.9) => {
          const midQuality = (low + high) / 2
          canvas.toBlob(
            (blob) => {
              if (!blob) {
                reject(new Error('压缩失败'))
                return
              }
              const currentSize = blob.size
              console.log(
                `当前质量：${(midQuality * 100).toFixed(1)}%，文件大小：${(currentSize / 1024).toFixed(2)}KB`
              )
              if (Math.abs(currentSize - targetSize) <= targetSize * 0.1 || high - low < 0.05) {
                // 符合误差范围或步长足够小，返回结果
                const finalQuality = Math.max(0.1, Math.min(0.9, midQuality))
                const compressedBlob = canvas.toBlob(
                  (finalBlob) => resolve(new File([finalBlob], file.name, { type: file.type })),
                  file.type,
                  finalQuality
                )
              } else if (currentSize < targetSize) {
                // 文件太小，调高质量
                tryCompress(midQuality, high)
              } else {
                // 文件太大，降低质量
                tryCompress(low, midQuality)
              }
            },
            file.type,
            midQuality
          )
        }
        tryCompress() // 启动二分查找
      }
      img.onerror = () => {
        reject(new Error('图片加载失败，请检查文件完整性'))
      }
    }
    reader.onerror = () => {
      reject(new Error('文件读取失败，请重试'))
    }
  })
}
// 微信浏览器内，微信 js-sdk 可直接禁用 Webview 大字体,设置网页字体为默认大小
export function handleFontSize() {
  console.log('WeixinJSBridge', window.top.WeixinJSBridge)
  if (
    typeof window.top.WeixinJSBridge == 'object' &&
    typeof window.top.WeixinJSBridge.invoke == 'function'
  ) {
    console.log('typeof window.top.WeixinJSBridge == objectwindow.top.WeixinJSBridge')
    window.top.WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
    window.top.WeixinJSBridge.on('menu:setfont', function () {
      window.top.WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
    })
  } else {
    console.log('setFontSizeCallback')
    document.addEventListener(
      'WeixinJSBridgeReady',
      () => {
        window.top.WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
        window.top.WeixinJSBridge.on('menu:setfont', function () {
          window.top.WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
        })
      },
      false
    )
  }
}
/**
 * 校验各种证件护照、军官证、户口本、返乡证、台胞证、身份证
 * @param {string} id
 * @param {string} type
 * @returns {boolean}
 */
export function checkID(id, type) {
  if (typeof id !== 'string') {
    throw new Error('不是字符串，请传入字符串')
  }
  if (type === 'passport' || type === '护照') {
    return /^([a-zA-z]|[0-9]){5,17}$/.test(id)
  } else if (type === 'officerCard' || type === 'officer' || type === '军官证') {
    return /^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/.test(id)
  } else if (type === 'accountCard' || type === 'account' || type === '户口本') {
    return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(id)
  } else if (type === 'HKCard' || type === 'HK' || type === '返乡证') {
    // 港澳居民来往内地通行证（返乡证）校验
    return /^([A-Z]\d{6,10}(\(\w{1}\))?)$/.test(id)
  } else if (type === 'TWCard' || type === 'TW' || type === '台胞证') {
    // 台湾居民来往大陆通行证校验
    return /^\d{8}|^[a-zA-Z0-9]{10}|^\d{18}$/.test(id)
  } else {
    var p = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
    var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
    var code = id.substring(17)
    if (p.test(id)) {
      var sum = 0
      for (var i = 0; i < 17; i++) {
        sum += id[i] * factor[i]
      }
      if (parity[sum % 11] == code.toUpperCase()) {
        var date6_14 = id.substring(6, 14)
        var pattern6_14 = /^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$/
        if (pattern6_14.test(date6_14)) {
          var year = date6_14.substring(0, 4)
          var month = date6_14.substring(4, 6)
          var date = date6_14.substring(6, 8)
          var date2 = new Date(year + '-' + month + '-' + date)
          if (date2 && date2.getMonth() == parseInt(month) - 1) {
            const date0_2 = id.substring(0, 2)
            var pattern0_2 = /^[1-9][0-9]/
            var provs = {
              11: '北京',
              12: '天津',
              13: '河北',
              14: '山西',
              15: '内蒙古',
              21: '辽宁',
              22: '吉林',
              23: '黑龙江 ',
              31: '上海',
              32: '江苏',
              33: '浙江',
              34: '安徽',
              35: '福建',
              36: '江西',
              37: '山东',
              41: '河南',
              42: '湖北 ',
              43: '湖南',
              44: '广东',
              45: '广西',
              46: '海南',
              50: '重庆',
              51: '四川',
              52: '贵州',
              53: '云南',
              54: '西藏 ',
              61: '陕西',
              62: '甘肃',
              63: '青海',
              64: '宁夏',
              65: '新疆',
              71: '台湾',
              81: '香港',
              82: '澳门'
            }
            if (pattern0_2.test(date0_2)) {
              if (provs[date0_2]) {
                return true
              }
              return false
            }
            return false
          }
          return false
        }
        return false
      }
      return false
    }
    return false
  }
}

// 身份证号码来计算生日
export function getBirthdayByIDNumber(idNumber) {
  if (idNumber.length !== 18) {
    throw new Error('身份证号码长度必须是18位')
  }
  const birthday = idNumber.substring(6, 14) // 提取生日部分
  const year = birthday.substring(0, 4) // 分离年、月、日
  const month = birthday.substring(4, 6)
  const day = birthday.substring(6, 8)
  return `${year}-${month}-${day}` // 返回生日的字符串表示
}

// 身份证号码来计算性别
export function getGenderByIdCard(idNumber) {
  if (idNumber.length !== 18) {
    throw new Error('身份证号码长度必须是18位')
  }
  // 获取身份证号码的第17位数字
  const genderCode = parseInt(idNumber.charAt(16), 10)
  // 根据第17位数字判断性别
  return genderCode % 2 === 0 ? '女' : '男'
}

// 返回当前地址？后的所有参数，const queryParams = getQueryParams(); 直接queryParams.qwe就能获取
export function getQueryParams() {
  const url = new URL(window.location) // 获取当前页面的URL
  const searchParams = new URLSearchParams(url.search) // 使用URLSearchParams解析查询字符串
  const params = Object.fromEntries(searchParams) // 获取所有参数
  return params
}
//将base64转换为File
export function base64ToFile(base64, fileName) {
  let arr = base64.split(',')
  let mime = arr[0].match(/:(.\*?);/)[1]
  let bstr = atob(arr[1])
  let n = bstr.length
  let u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], fileName, { type: mime })
}
//将base64转换为blob
export function base64ToBlob(base64Str) {
  var arr = base64Str.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new Blob([u8arr], { type: mime })
}

// 压缩Base64图片大小
// 使用示例
// const base64Image = '你的Base64编码图片字符串';
// compressBase64Image(base64Image, 800, 600, function(compressedBase64) {
//   console.log('压缩后的Base64图片:', compressedBase64);
// });
export function compressBase64Image(base64String, maxWidth, maxHeight, callback) {
  // 1. 解码Base64字符串
  const binaryString = atob(base64String)
  const len = binaryString.length
  const bytes = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i)
  }
  // 2. 创建Blob对象
  const blob = new Blob([bytes], { type: 'image/png' })
  // 3. 创建URL
  const url = URL.createObjectURL(blob)
  // 4. 调整图片大小
  const img = new Image()
  img.onload = function () {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const ratio = Math.min(maxWidth / img.width, maxHeight / img.height)
    const newWidth = img.width * ratio
    const newHeight = img.height * ratio
    canvas.width = newWidth
    canvas.height = newHeight
    ctx.drawImage(img, 0, 0, newWidth, newHeight)
    // 5. 编码回Base64
    canvas.toBlob(function (blob) {
      const reader = new FileReader()
      reader.readAsDataURL(blob)
      reader.onloadend = function () {
        const compressedBase64 = reader.result
        // 清理创建的URL
        URL.revokeObjectURL(url)
        // 调用回调函数，传入压缩后的Base64字符串
        callback(compressedBase64)
      }
    }, 'image/png')
  }
  img.src = url
}

// 按比例ratio压缩file类型图片大小
export function compressFileImage(file, ratio) {
  return new Promise((resolve, reject) => {
    // 读取文件并调整图片大小和质量
    if (file) {
      const reader = new FileReader()
      reader.onload = function (event) {
        const img = new Image()
        img.onload = function () {
          const canvas = document.createElement('canvas')
          const ctx = canvas.getContext('2d')
          const maxSize = 1024
          let width = img.width
          let height = img.height
          if (width > height) {
            if (width > maxSize) {
              height *= maxSize / width
              width = maxSize
            }
          } else {
            if (height > maxSize) {
              width *= maxSize / height
              height = maxSize
            }
          }
          canvas.width = width
          canvas.height = height
          ctx.drawImage(img, 0, 0, width, height)
          canvas.toBlob(
            function (blob) {
              const compressedFile = new File([blob], file.name, { type: file.type })
              // 在这里上传压缩后的文件 compressedFile
              resolve(compressedFile)
            },
            file.type,
            ratio
          )
        }
        img.src = event.target.result
      }
      reader.readAsDataURL(file)
    } else {
      console.log('图片压缩失败')
      reject('err')
    }
  })
}

// 返回base64图片大小
export function getBase64ImageSize(base64String) {
  // 移除Base64字符串中的任何数据URI前缀
  const base64WithoutPrefix = base64String.replace(/data:.*?;base64,/, '')
  // 将Base64编码的字符串解码为二进制数据
  const binaryString = atob(base64WithoutPrefix)
  // 将二进制数据转换为8位无符号整数值的数组
  const len = binaryString.length
  const bytes = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i)
  }
  // 创建Blob对象
  const blob = new Blob([bytes], { type: 'image/png' })
  // 返回Blob对象的大小
  return blob.size
}

// 按键防抖
export const antiShake = (fn, t) => {
  const delay = t || 500
  let timer
  return function () {
    const args = arguments
    if (timer) {
      clearTimeout(timer)
    }
    const callNow = !timer
    timer = setTimeout(() => {
      timer = null
    }, delay)
    if (callNow) fn.apply(this, args)
  }
}

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string}
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
      time = parseInt(time)
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  } else {
    time = +time
  }
  const d = new Date(time)
  const now = Date.now()

  const diff = (now - d) / 1000

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    return (
      d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
    )
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = url.split('?')[1]
  if (!search) {
    return {}
  }
  return JSON.parse(
    '{"' +
      decodeURIComponent(search)
        .replace(/"/g, '\\"')
        .replace(/&/g, '","')
        .replace(/=/g, '":"')
        .replace(/\+/g, ' ') +
      '"}'
  )
}

/**
 * 复制对象
 * @param {Object} obj
 */
export function copyObj(obj) {
  return JSON.parse(JSON.stringify(obj))
}

/**
 * 判断是否移动端
 */
export function isMobile() {
  if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
    return true
  } else {
    return false
  }
}

/**
 * 获取url参数
 * @param {参数名称} name
 */
export function getUrlKey(name) {
  try {
    return (
      decodeURIComponent(
        (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [
          ''
        ])[1].replace(/\+/g, '%20')
      ) || null
    )
  } catch (error) {
    return null
  }
}

/**
 * 判断是否ios
 */
export function isIOS() {
  return !!window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}

/**
 * 修复ios input 收回虚拟键盘后 页面元素偏移的bug
 */
export function fixedIOSInputBug() {
  let flag
  let myFunction
  if (isIOS()) {
    document.body.addEventListener('focusin', () => {
      // 软键盘弹起事件
      flag = true
      clearTimeout(myFunction)
    })
    document.body.addEventListener('focusout', () => {
      // 软键盘关闭事件
      flag = false
      if (!flag) {
        myFunction = setTimeout(function () {
          window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) // 重点  =======当键盘收起的时候让页面回到原始位置(这里的top可以根据需求改变，并不一定要回到页面顶部)
        }, 200)
      } else {
        return
      }
    })
  } else {
    return
  }
}
/**
 * 修复所有手机 input 收回虚拟键盘后 页面元素偏移的bug
 */
export function fixedALLInputBug() {
  let flag
  let myFunction
  document.body.addEventListener('focusin', () => {
    // 软键盘弹起事件
    flag = true
    clearTimeout(myFunction)
  })
  document.body.addEventListener('focusout', () => {
    // 软键盘关闭事件
    flag = false
    if (!flag) {
      myFunction = setTimeout(function () {
        window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) // 重点  =======当键盘收起的时候让页面回到原始位置(这里的top可以根据需求改变，并不一定要回到页面顶部)
      }, 200)
    } else {
      return
    }
  })
}

const handler = function (e) {
  e.preventDefault()
}
/**
 * 修复滚动穿透bug，只针对背景滚动，当前页不滚动
 */
export function fixedRollingThroughBug(value) {
  if (value) {
    document
      .getElementsByTagName('body')[0]
      .addEventListener('touchmove', handler, { passive: false })
  } else {
    document
      .getElementsByTagName('body')[0]
      .removeEventListener('touchmove', handler, { passive: false })
  }
}

/**
 *
 * @param {Date} date
 * @param {*Number} type 1 格式化年月日 2 格式为年月
 * @returns
 */
export function formatterDate(date, type) {
  const time = new Date(date)
  if (type === 1) {
    return `${time.getFullYear()}年${(time.getMonth() + 1).toString().padStart(2, '0')}月${time.getDate().toString().padStart(2, '0')}日`
  }
  if (type === 2) {
    return `${time.getFullYear()}年${(time.getMonth() + 1).toString().padStart(2, '0')}月`
  }
}

/**
 *
 * @param {Date} date
 * @param {*Number} type 1 格式化年-月-日 2 格式为年月202206
 * @returns
 */
export function processTime(date, type) {
  const time = new Date(date)
  if (type === 1) {
    return `${time.getFullYear()}-${(time.getMonth() + 1).toString().padStart(2, '0')}-${time.getDate().toString().padStart(2, '0')}`
  }
  if (type === 2) {
    return `${time.getFullYear()}${(time.getMonth() + 1).toString().padStart(2, '0')}`
  }
  if (type === 3) {
    return `${time.getFullYear()}-${(time.getMonth() + 1).toString().padStart(2, '0')}`
  }
}
/**
 * 格式化vant时间组件日期
 */
export const TimeFormatter = {
  year: '年',
  month: '月',
  day: '日',
  hour: '时',
  minute: '分'
}
